import type { ToolInstallVersionItem } from "@/modules/dev-env/common/types.ts";
import type { UnzipCompleteArgs } from "@common/archives-file-types.ts";
import type { MirrorWebsiteFile } from "@common/spider-types.ts";
import { Spider } from "@/ipc/spider.ts";
import { showMessageAndPrint } from "@/framework/util/log.ts";
import type { MirrorDataFilter } from "@/modules/dev-env/mirror/filter.ts";
import { keys } from "radash";
import type { MirrorQueryCondition } from "@/modules/dev-env/mirror/condition.ts";

/**
 * 下载源配置
 */
export interface EnvMirrorOptions {
  /**
   * ID
   */
  id: string;
  /**
   * 下载源名称
   */
  name: string;
  /**
   * 下载地址
   */
  url: string;
  /**
   * 变种版本，会作为安装路径的一层文件夹,比如JDK的各种发型版本: 'dragonwell', 'liberica'等
   *
   * 安装路径为：/path/to/versions/[variant]/[version]
   */
  variant?: string;

  /**
   * 官网地址
   */
  website?: Nil<string>;
}

/**
 * 环境/工具下载源
 */
export abstract class BaseEnvMirror implements EnvMirrorOptions {
  readonly id: string;
  readonly name: string;
  readonly url: string;
  readonly variant?: string;
  readonly website?: Nil<string>;

  /**
   * 使用压缩包安装时,是否多增加版本为最后一层目录
   */
  unzipToVersionDir?: boolean;

  protected _filters?: MirrorDataFilter[];
  protected _conditions?: MirrorQueryCondition[];

  protected constructor(options: EnvMirrorOptions) {
    this.id = options.id;
    this.name = options.name;
    this.url = options.url;
    this.variant = options.variant;
    this.website = options.website;
  }

  /**
   * 获取数据过滤器
   */
  getFilters(): MirrorDataFilter[] {
    return (this._filters ||= this.getFilters0?.() || []);
  }

  protected getFilters0?(): MirrorDataFilter[];

  /**
   * 获取查询条件
   */
  getConditions(): MirrorQueryCondition[] {
    return (this._conditions ||= this.getConditions0?.() || []);
  }

  protected getConditions0?(): MirrorQueryCondition[];

  protected getRequestUrl(query?: Record<string, any>) {
    let url = this.url;
    if (query) {
      const queryStr = keys(query)
        .filter(key => query[key] != null && query[key].toString().trim() !== "")
        .map(key => `${key}=${encodeURIComponent(query[key])}`)
        .join("&");
      if (url.indexOf("?") === -1) {
        url += `?${queryStr}`;
      } else {
        url += `&${queryStr}`;
      }
    }
    return url;
  }

  /**
   * 获取下载列表,默认以镜像站点方式抓取，如果不是，需要重写该方法
   * @param query url查询参数
   */
  async getDownloadList(query: Record<string, any>): Promise<ToolInstallVersionItem[]> {
    try {
      const requestUrl = this.getRequestUrl(query);
      const mirrorFiles = await Spider.getMirrorFiles(requestUrl);
      return this.getDownloadList0(mirrorFiles);
    } catch (e) {
      showMessageAndPrint(e);
      return [];
    }
  }

  /**
   * 根据镜像网站文件列表返回下载列表
   * @remarks 从{@link MirrorWebsites}中配置的下载源获取下载列表实现这个方法就可以, 如果是其他地址,子类需要重写{@link #getDownloadList}方法
   * @param files 镜像网站文件列表
   * @protected
   */
  protected getDownloadList0(files: MirrorWebsiteFile[]): ToolInstallVersionItem[] | Promise<ToolInstallVersionItem[]> {
    return [];
  }

  /**
   * 解压完成后的回调
   * @param e 解压完成返回参数
   * @param version 版本信息
   */
  afterUnzipComplete?(e: UnzipCompleteArgs, version: ToolInstallVersionItem): void | Promise<void>;
}
